﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Ranet.Olap.Core.DataDescription;
using System.Collections.Generic;
using Galaktika.BI.Silverlight.Controls.PivotGrid.Data;

namespace Galaktika.BI.Silverlight.Controls.PivotGrid.Controls
{
    public class ColumnsAreaControl : MembersAreaContol
    {
        /// <summary>
        /// Ключ - номер строки; значение - максимальная глубина DrillDown
        /// </summary>
        Dictionary<int, int> m_DrillDepth = new Dictionary<int, int>();

        public ColumnsAreaControl(PivotGridPanel grid)
            : base(grid)
        { 
        
        }

        private MemberControl AddMemberControl(MemberInfo member, int columnIndex, int rowIndex, out int memberSize, int drillDepth)
        {
            Grid MembersGrid = LayoutRoot;

            // Добавляем в случае необходимости строку и столбец
            ColumnDefinition current_col = null;
            if (MembersGrid.ColumnDefinitions.Count <= columnIndex)
            {
                current_col = new ColumnDefinition();
                current_col.Width = base.Default_Width;
                current_col.MinWidth = MembersAreaContol.MIN_WIDTH;
                MembersGrid.ColumnDefinitions.Add(current_col);
            }
            else
            {
                current_col = MembersGrid.ColumnDefinitions[columnIndex];
            }

            RowDefinition current_row = null;
            if (MembersGrid.RowDefinitions.Count <= rowIndex)
            {
                current_row = new RowDefinition();
                current_row.Height = base.Default_Height;
                current_row.MinHeight = MembersAreaContol.MIN_HEIGHT;
                MembersGrid.RowDefinitions.Add(current_row);
            }
            else
            {
                current_row = MembersGrid.RowDefinitions[rowIndex];
            }

            // Высоту строки рассчитываем с учетом максимальной глубины DrillDown
            if (m_DrillDepth.ContainsKey(rowIndex))
                m_DrillDepth[rowIndex] = Math.Max(m_DrillDepth[rowIndex], drillDepth);
            else
                m_DrillDepth[rowIndex] = drillDepth;
            if(m_DrillDepth[rowIndex] > 0)
            {
                double height = base.Default_Height.Value + MembersAreaContol.DRILLDOWN_SPACE_HEIGHT * m_DrillDepth[rowIndex];
                current_row.Height = new GridLength(Math.Max(current_row.Height.Value, height));
            }
            current_row.MinHeight = MembersAreaContol.DRILLDOWN_SPACE_HEIGHT * m_DrillDepth[rowIndex] + MembersAreaContol.MIN_HEIGHT;

            // Контрол для отображения самого элемента
            MemberControl member_ctrl = new ColumnMemberControl(member, drillDepth);
            MembersGrid.Children.Add(member_ctrl);
            Grid.SetColumn(member_ctrl, columnIndex);
            Grid.SetRow(member_ctrl, rowIndex);
            member_ctrl.Column = current_col;
            member_ctrl.Row = current_row;
            if (columnIndex == 0)
            {
                member_ctrl.ShowLeftBorder();
            }
            if (rowIndex == 0)
            {
                member_ctrl.ShowUpBorder();
            }

            // Подписываемся на Drill-операцию
            member_ctrl.DrillDownMember += new MemberActionEventHandler(OnDrillDownMember);
            // Подписываемся на контекстное меню
            member_ctrl.ShowContextMenu+=new EventHandler<MemberClickEventArgs>(OnShowContextMenu);

            // Если нет дочерних - добавляем в коллекцию "последних"
            if(member.Children.Count == 0)
                LovestMemberControls.Add(member_ctrl);

            // Дочерние элементы начинаются отображаться с той же колонки. только строкой ниже
            // Номер колонки с которой начнется отображение элемента
            int start_Child_ColumnIndex = columnIndex;
            // Текущий индекс колонки
            int current_Child_columnIndex = start_Child_ColumnIndex;
            // Размер добавляемого контрола (в колонках)
            int size = 0;
            foreach (MemberInfo child in member.Children)
            {
                AddMemberControl(child, current_Child_columnIndex, rowIndex + 1, out size, 0);
                current_Child_columnIndex = current_Child_columnIndex + size;
            }
            // Номер колонки, на которой закончится отображение элемента
            int end_Child_ColumnIndex = current_Child_columnIndex;
            int ChildrenSize = end_Child_ColumnIndex - start_Child_ColumnIndex;

            // Дрилл-даун дочерние отображаются в этой же строке, но с колонки следующей после самого элемента и всех дочерних
            // Номер колонки с которой начнется отображение элемента
            int start_DrillDown_ColumnIndex = ChildrenSize > 0 ? end_Child_ColumnIndex : columnIndex + 1;
            // Текущий индекс колонки
            int current_DrillDown_columnIndex = start_DrillDown_ColumnIndex;
            
            int indx = 0;
            // Размер добавляемого контрола (в строках)
            size = 0;
            foreach (MemberInfo child in member.DrilledDownChildren)
            {
                MemberControl drill_ctrl = AddMemberControl(child, current_DrillDown_columnIndex, rowIndex, out size, drillDepth + 1);
                current_DrillDown_columnIndex += size;

                if (indx == 0)
                {
                    drill_ctrl.ShowLeftBorder();
                }
                indx++;
            }
            // Номер колонки, на которой закончится отображение элемента
            int end_DrillDown_ColumnIndex = current_DrillDown_columnIndex;
            int DrillDownChildrenSize = end_DrillDown_ColumnIndex - start_DrillDown_ColumnIndex;


            // Растягиваем элемент если есть дочерние
            int span_Size = 1;
            int span_Size_WithChildren = 1;
            if (ChildrenSize > 1)
            {
                span_Size_WithChildren = ChildrenSize;
            }
            if (member.DrilledDownChildren.Count > 0)
            {
                span_Size = span_Size_WithChildren + DrillDownChildrenSize;
            }
            else
            {
                span_Size = span_Size_WithChildren;
            }

            if (span_Size > 1)
                Grid.SetColumnSpan(member_ctrl, span_Size);

            // Вычисляем смещение  - куда именно должен попасть сплиттер с учетом того что ячека может быть объединенной
            int splitter_offset = span_Size_WithChildren > 0 ? span_Size_WithChildren - 1 : span_Size_WithChildren;
            // Добавляем Splitter для изменения ширины
            Add_VertSplitter(MembersGrid, columnIndex + splitter_offset, rowIndex, 1);

            memberSize = span_Size;
            return member_ctrl;
        }

        public override void Initialize(MemberInfoCollection members)
        {
            m_DrillDepth.Clear();

            Grid MembersGrid = LayoutRoot;
            MembersGrid.Children.Clear();
            MembersGrid.ColumnDefinitions.Clear();
            MembersGrid.RowDefinitions.Clear();

            base.Initialize(members);

            if (members != null)
            {
                int size = 0;
                int columnIndex = 0;
                int rowIndex = 0;
                foreach(MemberInfo member in members)
                {
                    AddMemberControl(member, columnIndex, rowIndex, out size, 0);
                    columnIndex += size;
                }

                // Добавляем Splitter(ы) для изменения высоты
                if (MembersGrid.RowDefinitions.Count > 0 && MembersGrid.ColumnDefinitions.Count > 0)
                {
                    // Фиктивная строка, которая предназначена только для того, чтобы менять размеры последней колонки
                    RowDefinition row_split = new RowDefinition();
                    row_split.Height = GridLength.Auto;
                    MembersGrid.RowDefinitions.Add(row_split);

                    for (int i = 0; i < MembersGrid.RowDefinitions.Count - 1; i++)
                    {
                        Add_HorzSplitter(MembersGrid, 0, i, MembersGrid.ColumnDefinitions.Count);
                    }
                }

                // Добавляем фиктивную колонку для изменения ширины последнего элемента
                if (MembersGrid.ColumnDefinitions.Count > 0)
                {
                    // Фиктивная колонка, которая предназначена только для того, чтобы менять размеры последней колонки
                    ColumnDefinition column_split = new ColumnDefinition();
                    column_split.Width = GridLength.Auto;
                    MembersGrid.ColumnDefinitions.Add(column_split);
                }
            }
        }
    }
}
